home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-06-05 | 57.7 KB | 1,346 lines |
- Newsgroups: comp.sources.misc
- From: daveg@csvax.caltech.edu (David Gillespie)
- Subject: v13i044: Emacs Calculator 1.01, part 18/19
- Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
-
- Posting-number: Volume 13, Issue 44
- Submitted-by: daveg@csvax.caltech.edu (David Gillespie)
- Archive-name: gmcalc/part18
-
- ---- Cut Here and unpack ----
- #!/bin/sh
- # this is part 18 of a multipart archive
- # do not concatenate these parts, unpack them in order with /bin/sh
- # file calc.texinfo continued
- #
- CurArch=18
- if test ! -r s2_seq_.tmp
- then echo "Please unpack part 1 first!"
- exit 1; fi
- ( read Scheck
- if test "$Scheck" != $CurArch
- then echo "Please unpack part $Scheck next!"
- exit 1;
- else exit 0; fi
- ) < s2_seq_.tmp || exit 1
- echo "x - Continuing file calc.texinfo"
- sed 's/^X//' << 'SHAR_EOF' >> calc.texinfo
- XPairs of @kbd{Z `} and @kbd{Z '} characters may be nested.
- X
- XIf a keyboard macro halts due to an error in between a @kbd{Z `} and
- X@kbd{Z '}, the saved values will be restored correctly even though
- Xthe macro never reaches the @kbd{Z '} command. Thus you can use
- X@kbd{Z `} and @kbd{Z '} without having to worry about what happens
- Xin exceptional conditions.
- X
- XIf you type @kbd{Z `} ``live'' (not in a keyboard macro), Calc puts
- Xyou into a ``recursive edit.'' You can tell you are in a recursive
- Xedit because there will be extra square brackets in the mode line,
- Xas in @samp{[(Calculator)]}. These brackets will go away when you
- Xtype the matching @kbd{Z '} command. The modes and quick variables
- Xwill be saved and restored in just the same way as if actual keyboard
- Xmacros were involved.
- X
- XThe modes saved by @kbd{Z `} and @kbd{Z '} are the current precision
- Xand word size, the angular mode (Deg, Rad, or HMS), the simplification
- Xmode, the matrix mapping direction, Algebraic mode, Symbolic mode,
- XFraction mode, and the current complex mode (Polar or Rectangular).
- XThe ten ``quick'' variables' values (or lack thereof) are also saved.
- X
- XMost mode-setting commands act as toggles, but with a numeric prefix
- Xthey force the mode either on (positive prefix) or off (negative
- Xor zero prefix). Since you don't know what the environment might
- Xbe when you invoke your macro, it's best to use prefix arguments
- Xfor all mode-setting commands inside the macro.
- X
- XThe contents of the stack and trail, values of non-quick variables, and
- Xother settings such as the various display modes, are @emph{not}
- Xaffected by @kbd{Z `} and @kbd{Z '}.
- X
- X@node Queries in Macros, , Local Values in Macros, Keyboard Macros
- X@subsection Queries in Keyboard Macros
- X
- X@kindex Z =
- X@pindex calc-kbd-report
- XThe @kbd{Z =} (@code{calc-kbd-report}) command displays an informative
- Xmessage including the value on the top of the stack. You are prompted
- Xto enter a string. That string, along with the top-of-stack value,
- Xis displayed unless @kbd{m w} (@code{calc-working}) has been used
- Xto turn such messages off.
- X
- X@kindex Z #
- X@pindex calc-kbd-query
- XThe @kbd{Z #} (@code{calc-kbd-query}) command displays a prompt message
- X(which you enter during macro definition), then does an algebraic entry
- Xwhich takes its input from the keyboard, even during macro execution.
- XThis command allows your keyboard macros to accept numbers or formulas
- Xas interactive input. All the normal conventions of algebraic input,
- Xincluding the use of @kbd{$} characters, are supported.
- X@xref{Kbd Macro Query, , , emacs, the Emacs manual}, for a description of
- X@kbd{C-x q} (@code{kbd-macro-query}), the standard Emacs way to accept
- Xkeyboard input during a keyboard macro. In particular, you can use
- X@kbd{C-x q} to enter a recursive edit, which allows the user to perform
- Xany Calculator operations interactively before pressing @kbd{C-M-c} to
- Xreturn control to the keyboard macro.
- X
- X@node Algebraic Definitions, Lisp Definitions, Keyboard Macros, Programming
- X@section Programming with Algebraic Formulas
- X
- X@kindex Z F
- X@pindex calc-user-define-formula
- X@cindex Programming with algebraic formulas
- XAnother way to create a new Calculator command uses algebraic formulas.
- XThe @kbd{Z F} (@code{calc-user-define-formula}) command stores the
- Xformula at the top of the stack as the definition for a key. This
- Xcommand prompts for five things: The key, the command name, the function
- Xname, the argument list, and the behavior of the command when given
- Xnon-numeric arguments.
- X
- XFor example, suppose we type @kbd{' a+2b @key{RET}} to push the formula
- X@samp{a + 2*b} onto the stack. We now type @kbd{Z F m} to define this
- Xformula on the @kbd{z m} key sequence. The next prompt is for a command
- Xname, beginning with @samp{calc-}, which should be the long (@kbd{M-x}) form
- Xfor the new command. If you simply press @key{RET}, a default name like
- X@code{calc-User-m} will be constructed. In our example, suppose we enter
- X@kbd{spam @key{RET}} to define the new command as @code{calc-spam}.
- X
- XIf you want to give the formula a long-style name only, you can press
- X@key{SPC} or @key{RET} when asked which single key to use. For example
- X@kbd{Z F @key{RET} spam @key{RET}} defines the new command as @code{calc-spam},
- Xwith no keyboard equivalent.
- X
- XThe third prompt is for a function name. The default is to use the same
- Xname as the command name but with @samp{calcFunc-} in place of
- X@samp{calc-}. This is the name you will use if you want to enter your
- Xnew function in an algebraic formula. Suppose we enter @kbd{yow @key{RET}}.
- XThen the new function can be invoked by pushing two numbers on the
- Xstack and typing @kbd{z m} or @kbd{x spam}, or by entering the algebraic
- Xformula @samp{yow(x,y)}.@refill
- X
- XThe fourth prompt is for the function's argument list. This is used to
- Xassociate values on the stack with the variables that appear in the formula.
- XThe default is a list of all variables which appear in the formula, sorted
- Xinto alphabetical order. In our case, the default would be @samp{(a b)}.
- XThis means that, when the user types @kbd{z m}, the Calculator will remove
- Xtwo numbers from the stack, substitute these numbers for @samp{a} and
- X@samp{b} (respectively) in the formula, then simplify the formula and
- Xpush the result on the stack. In other words, @kbd{10 @key{RET} 100 z m}
- Xwould replace the 10 and 100 on the stack with the number 210, which is
- X@samp{a + 2*b} with @samp{a=10} and @samp{b=100}. Likewise, the formula
- X@samp{yow(10, 100)} will be evaluated by substituting @samp{a=10} and
- X@samp{b=100} in the definition.
- X
- XYou can rearrange the order of the names before pressing @key{RET} to
- Xcontrol which stack positions go to which variables in the formula. If
- Xyou remove a variable from the argument list, that variable will be left
- Xin symbolic form by the command. Thus using an argument list of @samp{(b)}
- Xfor our function would cause @kbd{10 z m} to replace the 10 on the stack
- Xwith the formula @samp{a + 20}. If we had used an argument list of
- X@samp{(b a)}, the result with inputs 10 and 100 would have been 120.
- X
- XThe final prompt is a y-or-n question concerning what to do if symbolic
- Xarguments are given to your function. If you answer @kbd{y}, then
- Xexecuting @kbd{z m} (using the original argument list @samp{(a b)}) with
- Xarguments @samp{10} and @samp{x} will leave the function in symbolic
- Xform, i.e., @samp{yow(10,x)}. On the other hand, if you answer @kbd{n},
- Xthen the formula will always be expanded, even for non-constant
- Xarguments: @samp{10 + 2 * x}. If you never plan to feed algebraic
- Xformulas to your new function, it doesn't matter how you answer this
- Xquestion.@refill
- X
- X@kindex Z G
- X@pindex calc-get-user-defn
- XOnce you have defined a formula on a key, you can retrieve this formula
- Xwith the @kbd{Z G} (@code{calc-user-define-get-defn}) command. Press a
- Xkey, and this command pushes the formula that was used to define that
- Xkey onto the stack. You will get an error message if the key is undefined,
- Xor if the key was not defined by a @kbd{Z F} command.@refill
- X
- XThe @kbd{Z E} (@code{calc-user-define-edit}) command on a key that has
- Xbeen defined by a formula uses a variant of the @code{calc-edit} command
- Xto edit the defining formula. Press @kbd{C-c C-c} to finish editing and
- Xstore the new formula back in the definition, or kill the formula-editing
- Xbuffer with @kbd{C-x k} to cancel the edit. (The argument list and other
- Xproperties of the definition are unchanged; to adjust the argument list,
- Xyou must use @kbd{Z G} to grab the formula onto the stack and then
- Xre-execute the @kbd{Z F} command.)
- X
- XAs usual, the @kbd{Z P} command records your definition permanently.
- XIn this case it will permanently record all three of the relevant
- Xdefinitions: the key, the command, and the function.
- X
- XYou may find it useful to turn off the default simplifications with
- X@kbd{m O} (@code{calc-no-simplify-mode}) when entering a formula to be
- Xused as a function definition. For example, the formula @samp{deriv(a^2,v)}
- Xwhich might be used to define a new function @samp{dsqr(a,v)} will be
- X``simplified'' to 0 immediately upon entry since @code{deriv} considers
- X@samp{a} to be constant with respect to @samp{v}. Turning off
- Xdefault simplifications cures this problem: the definition will be stored
- Xin symbolic form without ever activating the @code{deriv} function. Press
- X@kbd{m D} to turn the default simplifications back on afterwards.
- X
- X@node Lisp Definitions, , Algebraic Definitions, Programming
- X@section Programming with Lisp
- X
- XThe Calculator can be programmed quite extensively in Lisp. All you
- Xdo is write a normal Lisp function definition, but with @code{defmath}
- Xin place of @code{defun}. This has the same form as @code{defun}, but it
- Xautomagically replaces calls to standard Lisp functions like @code{+} and
- X@code{zerop} with calls to the corresponding functions in Calc's own library.
- XThus you can write natural-looking Lisp code which operates on all of the
- Xstandard Calculator data types. You can then use @kbd{Z D} if you wish to
- Xbind your new command to a @kbd{z}-prefix key sequence. The @kbd{Z E} command
- Xwill not edit a Lisp-based definition.
- X
- XEmacs Lisp is described in the Emacs Lisp Reference Manual. This section
- Xassumes a familiarity with Lisp programming concepts; if you do not know
- XLisp, you may find keyboard macros to be an easier way to program the
- XCalculator.
- X
- X@menu
- X* Defining Functions::
- X* Defining Simple Commands::
- X* Defining Stack Commands::
- X* Argument Qualifiers::
- X* Example Definitions::
- X* Internals::
- X@end menu
- X
- X@node Defining Functions, Defining Simple Commands, Lisp Definitions, Lisp Definitions
- X@subsection Defining New Functions
- X
- X@findex defmath
- XThe @code{defmath} function (actually a Lisp macro) is like @code{defun}
- Xexcept that code in the body of the definition can make use of the full
- Xrange of Calculator data types. The prefix @samp{calcFunc-} is added
- Xto the specified name to get the actual Lisp function name. As a simple
- Xexample,
- X
- X@example
- X(defmath myfact (n)
- X (if (> n 0)
- X (* n (myfact (1- n)))
- X 1))
- X@end example
- X
- X@noindent
- XThis actually expands to the code,
- X
- X@example
- X(defun calcFunc-myfact (n)
- X (if (math-posp n)
- X (math-mul n (calcFunc-myfact (math-add n -1)))
- X 1))
- X@end example
- X
- X@noindent
- XThis function can be used in algebraic expressions, e.g., @samp{myfact(5)}.
- X
- XThe @samp{myfact} function as it is defined above has the bug that an
- Xexpression @samp{myfact(a+b)} will be simplified to 1 because the
- Xformula @samp{a+b} is not considered to be @code{posp}. A robust
- Xfactorial function would be written along the following lines:
- X
- X@example
- X(defmath myfact (n)
- X (if (> n 0)
- X (* (myfact (1- n)))
- X (if (= n 0)
- X 1
- X nil))) ; this could be simplified as: (and (= n 0) 1)
- X@end example
- X
- XIf a function returns @code{nil}, it is left unsimplified by the Calculator
- X(except that its arguments will be simplified). Thus, @samp{myfact(a+1+2)}
- Xwill be simplified to @samp{myfact(a+3)} but no further. Beware that every
- Xtime the Calculator reexamines this formula it will attempt to resimplify
- Xit, so your function ought to detect the returning-@code{nil} case as
- Xefficiently as possible.
- X
- XThe following standard Lisp functions are treated by @code{defmath}:
- X@code{+}, @code{-}, @code{*}, @code{/}, @code{%}, @code{^} or
- X@code{expt}, @code{=}, @code{<}, @code{>}, @code{<=}, @code{>=},
- X@code{/=}, @code{1+}, @code{1-}, @code{logand}, @code{logior}, @code{logxor},
- X@code{logandc2}, @code{lognot}. Also, @code{~=} is an abbreviation for
- X@code{math-nearly-equal}, which is useful in implementing Taylor series.@refill
- X
- XFor other functions @var{func}, if a function by the name
- X@samp{calcFunc-@var{func}} exists it is used, otherwise if a function by the
- Xname @samp{math-@var{func}} exists it is used, otherwise if @var{func} itself
- Xis defined as a function it is used, otherwise @samp{calcFunc-@var{func}} is
- Xused on the assumption that this is a to-be-defined math function. Also, if
- Xthe function name is quoted as in @samp{('integerp a)} the function name is
- Xalways used exactly as written.@refill
- X
- XVariable names have @samp{var-} prepended to them unless they appear in
- Xthe function's argument list or in an enclosing @code{let}, @code{let*},
- X@code{for}, or @code{foreach} form,
- Xor their names already contain a @samp{-} character. Thus a reference to
- X@samp{foo} is the same as a reference to @samp{var-foo}.@refill
- X
- XA few other Lisp extensions are available in @code{defmath} definitions:
- X
- X@itemize @bullet
- X@item
- XThe @code{elt} function accepts any number of index variables.
- XNote that Calc vectors are stored as Lisp lists whose first
- Xelement is the symbol @code{vec}; thus, @samp{(elt v 2)} yields
- Xthe second element of vector @code{v}, and @samp{(elt m i j)}
- Xyields one element of a Calc matrix.
- X
- X@item
- XThe @code{setq} function has been extended to act like the Common
- XLisp @code{setf} function. (The name @code{setf} is recognized as
- Xa synonym of @code{setq}.) Specifically, the first argument of
- X@code{setq} can be an @code{nth}, @code{elt}, @code{car}, or @code{cdr} form,
- Xin which case the effect is to store into the specified
- Xelement of a list. Thus, @samp{(setq (elt m i j) x)} stores @code{x}
- Xinto one element of a matrix.
- X
- X@item
- XA @code{for} looping construct is available. For example,
- X@samp{(for ((i 0 10)) body)} executes @code{body} once for each
- Xbinding of @code{i} from zero to 10. This is like a @code{let}
- Xform in that @code{i} is temporarily bound to the loop count
- Xwithout disturbing its value outside the @code{for} construct.
- XNested loops, as in @samp{(for ((i 0 10) (j 0 (1- i) 2)) body)},
- Xare also available. For each value of @code{i} from zero to 10,
- X@code{j} counts from 0 to @samp{i-1} in steps of two. Note that
- X@code{for} has the same general outline as @code{let}, except
- Xthat each element of the header is a list of three or four
- Xthings, not just two.
- X
- X@item
- XThe @code{foreach} construct loops over elements of a list.
- XFor example, @samp{(foreach ((x (cdr v))) body)} executes
- X@code{body} with @code{x} bound to each element of Calc vector
- X@code{v} in turn. The purpose of @code{cdr} here is to skip over
- Xthe initial @code{vec} symbol in the vector.
- X
- X@item
- XThe @code{break} function breaks out of the innermost enclosing
- X@code{while}, @code{for}, or @code{foreach} loop. If given a
- Xvalue, as in @samp{(break x)}, this value is returned by the
- Xloop. (Lisp loops otherwise always return @code{nil}.)
- X
- X@item
- XThe @code{return} function prematurely returns from the enclosing
- Xfunction. For example, @samp{(return (+ x y))} returns @samp{x+y}
- Xas the value of a function. You can use @code{return} anywhere
- Xinside the body of the function.
- X@end itemize
- X
- XNon-integer numbers (and extremely large integers) cannot be included
- Xdirectly into a @code{defmath} definition. This is because the Lisp
- Xreader will fail to parse them long before @code{defmath} ever gets control.
- XInstead, use the notation, @samp{:"3.1415"}. In fact, any algebraic
- Xformula can go between the quotes. For example,
- X
- X@example
- X(defmath sqexp (x) ; sqexp(x) == sqrt(exp(x)) == exp(x*0.5)
- X (and (numberp x)
- X (exp :"x * 0.5")))
- X@end example
- X
- Xexpands to
- X
- X@example
- X(defun calcFunc-sqexp (x)
- X (and (math-numberp x)
- X (calcFunc-exp (math-mul x '(float 5 -1)))))
- X@end example
- X
- XNote the use of @code{numberp} as a guard to ensure that the argument is
- Xa number first, returning @code{nil} if not. The exponential function
- Xcould itself have been included in the expression, if we had preferred:
- X@samp{:"exp(x * 0.5)"}. As another example, the multiplication-and-recursion
- Xstep of @code{myfact} could have been written
- X
- X@example
- X:"n * myfact(n-1)"
- X@end example
- X
- XIf a file named @file{.emacs} exists in your home directory, Emacs reads
- Xand executes the Lisp forms in this file as it starts up. While it may
- Xseem like a good idea to put your favorite @code{defmath} commands here,
- Xthis has the unfortunate side-effect that the entire Calculator must be
- Xloaded in to process the @code{defmath} commands whether or not you will
- Xactually use the Calculator! A better effect can be had by writing
- X
- X@example
- X(setq calc-defs '(
- X (defmath ... )
- X (defmath ... )
- X))
- X@end example
- X
- X@noindent
- X@vindex calc-defs
- XIf the @code{calc-defs} variable contains a list of Lisp expressions
- Xwhen the Calculator is started, those expressions will be executed and the
- X@code{calc-defs} variable cleared. Thus your @code{defmath} commands will
- Xbe executed only once, and only when the Calculator is first used. If you
- Xmust edit these definitions, simply re-execute the @code{setq} command
- Xusing @kbd{C-x C-e} and restart the Calculator with @kbd{M-x calc}.
- X
- X@node Defining Simple Commands, Defining Stack Commands, Defining Functions, Lisp Definitions
- X@subsection Defining New Simple Commands
- X
- X@findex interactive
- XIf a @code{defmath} form contains an @code{interactive} clause, it defines
- Xa Calculator command. Actually such a @code{defmath} results in @emph{two}
- Xfunction definitions: One, a @samp{calcFunc-} function as was just described,
- Xwith the @code{interactive} clause removed. Two, a @samp{calc-} function
- Xwith a suitable @code{interactive} clause and some sort of wrapper to make
- Xthe command work in the Calc environment.
- X
- XIn the simple case, the @code{interactive} clause has the same form as
- Xfor normal Emacs Lisp commands:
- X
- X@example
- X(defmath increase-precision (delta)
- X "Increase precision by DELTA." ; This is the "documentation string"
- X (interactive "p") ; Register this as a M-x-able command
- X (setq calc-internal-prec (+ calc-internal-prec delta)))
- X@end example
- X
- XThis expands to the pair of definitions,
- X
- X@example
- X(defun calc-increase-precision (delta)
- X "Increase precision by DELTA."
- X (interactive "p")
- X (calc-wrapper
- X (setq calc-internal-prec (math-add calc-internal-prec delta))))
- X
- X(defun calcFunc-increase-precision (delta)
- X "Increase precision by DELTA."
- X (setq calc-internal-prec (math-add calc-internal-prec delta)))
- X@end example
- X
- X@noindent
- Xwhere in this case the latter function would never really be used! Note
- Xthat since the Calculator stores small integers as plain Lisp integers,
- Xthe @code{math-add} function will work just as well as the native
- X@code{+} even when the intent is to operate on native Lisp integers.
- X
- X@findex calc-wrapper
- XThe @samp{calc-wrapper} call invokes a macro which surrounds the body of
- Xthe function with code that looks like this:
- X
- X@example
- X (let ((calc-command-flags nil))
- X (unwind-protect
- X (progn
- X (save-excursion
- X (calc-select-buffer)
- X @emph{body of function})
- X (calc-finish-command))
- X (calc-cleanup-command)))
- X@end example
- X
- X@findex calc-select-buffer
- XThe @code{calc-select-buffer} function selects the @samp{*Calculator*}
- Xbuffer if necessary, say, because the command was invoked from inside
- Xthe @samp{*Calc Trail*} window.
- X
- X@findex calc-finish-command
- XThe @code{calc-finish-command} function recomputes the line numbers
- Xfor all stack entries if they have been changed.
- XAlso, if the @code{clear-message} flag is set
- Xit executes @samp{(message "")} to clear any lingering ``Working'' message
- Xout of the echo area.@refill
- X
- X@findex calc-cleanup-command
- XThe @code{calc-cleanup-command} function normally aligns the stack window
- Xso that the top element of the stack is visible at the
- Xbottom of the window, and moves the cursor down to the bottom line.
- XThis can be suppressed by setting the @code{no-align}
- Xflag as described below. Also, it clears the Inverse and Hyperbolic
- Xflags (unless the @code{keep-flags} flag has been set), and updates the
- Xdisplay of the mode line.@refill
- X
- X@findex calc-set-command-flag
- XYou can call, for example, @code{(calc-set-command-flag 'no-align)} to set
- Xthe above-mentioned command flags.
- X
- X@node Defining Stack Commands, Argument Qualifiers, Defining Simple Commands, Lisp Definitions
- X@subsection Defining New Stack-Based Commands
- X
- XTo define a new computational command which takes and/or leaves arguments
- Xon the stack, a special form of @code{interactive} clause is used.
- X
- X@example
- X(interactive @var{num} @var{tag})
- X@end example
- X
- X@noindent
- Xwhere @var{num} is an integer, and @var{tag} is a string. The effect is
- Xto pop @var{num} values off the stack, resimplify them by calling
- X@code{calc-normalize}, and hand them to your function according to the
- Xfunction's argument list. Your function may include @code{&optional} and
- X@code{&rest} parameters, so long as calling the function with @var{num}
- Xparameters is legal.
- X
- XYour function must return either a number or a formula in a form
- Xacceptable to Calc, or a list of such numbers or formulas. These value(s)
- Xare pushed onto the stack when the function completes. They are also
- Xrecorded in the Calc Trail buffer on a line beginning with @var{tag},
- Xa string of (normally) four characters or less. If you omit @var{tag}
- Xor use @code{nil} as a tag, the result is not recorded in the trail.
- X
- XAs an example, the definition
- X
- X@example
- X(defmath myfact (n)
- X "Compute the factorial of the integer at the top of the stack."
- X (interactive 1 "fact")
- X (if (> n 0)
- X (* (myfact (1- n)))
- X (and (= n 0) 1)))
- X@end example
- X
- X@noindent
- Xis a version of the factorial function shown previously which can be used
- Xas a command as well as an algebraic function. It expands to
- X
- X@example
- X(defun calc-myfact ()
- X "Compute the factorial of the integer at the top of the stack."
- X (interactive)
- X (calc-slow-wrapper
- X (calc-enter-result 1 "fact"
- X (cons 'calcFunc-myfact (calc-top-list-n 1)))))
- X
- X(defun calcFunc-myfact (n)
- X "Compute the factorial of the integer at the top of the stack."
- X (if (math-posp n)
- X (math-mul n (calcFunc-myfact (math-add n -1)))
- X (and (math-zerop n) 1)))
- X@end example
- X
- X@findex calc-slow-wrapper
- XThe @code{calc-slow-wrapper} function is a version of @code{calc-wrapper}
- Xthat automatically puts up a @samp{Working...} message before the
- Xcomputation begins. (This message can be turned off by the user
- Xwith a @kbd{m w} (@code{calc-working}) command.)
- X
- X@findex calc-top-list-n
- XThe @code{calc-top-list-n} function returns a list of the specified number
- Xof values from the top of the stack. It resimplifies each value by
- Xcalling @code{calc-normalize}. If its argument is zero it returns an
- Xempty list. It does not actually remove these values from the stack.
- X
- X@findex calc-enter-result
- XThe @code{calc-enter-result} function takes an integer @var{num} and string
- X@var{tag} as described above, plus a third argument which is either a
- XCalculator data object or a list of such objects. These objects are
- Xresimplified and pushed onto the stack after popping the specified number
- Xof values from the stack. If @var{tag} is non-@code{nil}, the values
- Xbeing pushed are also recorded in the trail.
- X
- XNote that if @code{calcFunc-myfact} returns @code{nil} this represents
- X``leave the function in symbolic form.'' To return an actual empty list,
- Xin the sense that @code{calc-enter-result} will push zero elements back
- Xonto the stack, you should return the special value @samp{'(nil)}, a list
- Xcontaining the single symbol @code{nil}.
- X
- XThe @code{interactive} declaration can actually contain a limited
- XEmacs-style code string as well which comes just before @var{num} and
- X@var{tag}. Currently only Emacs code supported is @samp{"p"}, as in
- X
- X@example
- X(defmath foo (a b &optional c)
- X (interactive "p" 2 "foo")
- X @var{body})
- X@end example
- X
- XIn this example, the command @code{calc-foo} will evaluate the expression
- X@samp{foo(a,b)} if executed with no argument, or @samp{foo(a,b,n)} if
- Xexecuted with a numeric prefix argument of @samp{n}.
- X
- XThe other code string allowed is @samp{"m"} (unrelated to the usual @samp{"m"}
- Xcode as used with @code{defun}). It uses the numeric prefix argument as the
- Xnumber of objects to remove from the stack and pass to the function.
- XIn this case, the integer @var{num} serves as a default number of
- Xarguments to be used when no prefix is supplied.
- X
- X@node Argument Qualifiers, Example Definitions, Defining Stack Commands, Lisp Definitions
- X@subsection Argument Qualifiers
- X
- XAnywhere a parameter name can appear in the parameter list you can also use
- Xan @dfn{argument qualifier}. Thus the general form of a definition is:
- X
- X@example
- X(defmath @var{name} (@var{param} @var{param...}
- X &optional @var{param} @var{param...}
- X &rest @var{param})
- X @var{body})
- X@end example
- X
- Xwhere each @var{param} is either a symbol or a list of the form
- X
- X@example
- X(@var{qual} @var{param})
- X@end example
- X
- XThe following qualifiers are recognized:
- X
- X@table @samp
- X@item complete
- X@findex complete
- XThe argument must not be an incomplete vector, interval, or complex number.
- X(This is rarely needed since the Calculator itself will never call your
- Xfunction with an incomplete argument. But there is nothing stopping your
- Xown Lisp code from calling your function with an incomplete argument.)@refill
- X
- X@item integer
- X@findex integer
- XThe argument must be an integer. If it is an integer-valued float
- Xit will be accepted but converted to integer form. Non-integers and
- Xformulas are rejected.
- X
- X@item natnum
- X@findex natnum
- XLike @samp{integer}, but the argument must be non-negative.
- X
- X@item fixnum
- X@findex fixnum
- XLike @samp{integer}, but the argument must fit into a native Lisp integer,
- Xwhich on most systems means less than 2^23 in absolute value. The
- Xargument is converted into Lisp-integer form if necessary.
- X
- X@item float
- X@findex float
- XThe argument is converted to floating-point format if it is a number or
- Xvector. If it is a formula it is left alone. (The argument is never
- Xactually rejected by this qualifier.)
- X
- X@item @var{pred}
- XThe argument must satisfy predicate @var{pred}, which is one of the
- Xstandard Calculator predicates. @xref{Predicates}.
- X
- X@item not-@var{pred}
- XThe argument must @emph{not} satisfy predicate @var{pred}.
- X@end table
- X
- XFor example,
- X
- X@example
- X(defmath foo (a (constp (not-matrixp b)) &optional (float c)
- X &rest (integer d))
- X @var{body})
- X@end example
- X
- X@noindent
- Xexpands to
- X
- X@example
- X(defun calcFunc-foo (a b &optional c &rest d)
- X (and (math-matrixp b)
- X (math-reject-arg b 'not-matrixp))
- X (or (math-constp b)
- X (math-reject-arg b 'constp))
- X (and c (setq c (math-check-float c)))
- X (setq d (mapcar 'math-check-integer d))
- X @var{body})
- X@end example
- X
- X@noindent
- Xwhich performs the necessary checks and conversions before executing the
- Xbody of the function.
- X
- X@node Example Definitions, Internals, Argument Qualifiers, Lisp Definitions
- X@subsection Example Definitions
- X
- XThis section includes some Lisp programming examples on a larger scale.
- XThese programs make use of many of the Calculator's internal functions
- X(@pxref{Internals}).
- X
- X@menu
- X* Sine Example::
- X@end menu
- X
- X@node Sine Example, , Example Definitions, Example Definitions
- X@subsubsection The Sine Function
- X
- XA somewhat limited sine function could be defined as follows, using the
- Xwell-known Taylor series expansion for @samp{sin(x)}:
- X
- X@example
- X(defmath mysin ((float (anglep x)))
- X (interactive 1 "mysn")
- X (setq x (to-radians x)) ; Convert from current angular mode.
- X (let ((sum x) ; Initial term of Taylor expansion of sin.
- X newsum
- X (nfact 1) ; "nfact" equals "n" factorial at all times.
- X (xnegsqr :"-(x^2)")) ; "xnegsqr" equals -x^2.
- X (for ((n 3 100 2)) ; Upper limit of 100 is a good precaution.
- X (working "mysin" sum) ; Display "Working" message, if enabled.
- X (setq nfact (* nfact (1- n) n)
- X x (* x xnegsqr)
- X newsum (+ sum (/ x nfact)))
- X (if (~= newsum sum) ; If newsum is "nearly equal to" sum,
- X (break)) ; then we are done.
- X (setq sum newsum))
- X sum))
- X@end example
- X
- XThe actual @code{sin} function in Calc works by first reducing the problem
- Xto a sine or cosine of a nonnegative number less than @samp{pi/4}. This
- Xensures that the Taylor series will converge quickly. Also, the calculation
- Xis carried out with two extra digits of precision to guard against cumulative
- Xround-off in @samp{sum}. Finally, complex arguments are allowed and handled
- Xby a separate algorithm.
- X
- X@example
- X(defmath mysin ((float (scalarp x)))
- X (interactive 1 "mysn")
- X (setq x (to-radians x)) ; Convert from current angular mode.
- X (with-extra-prec 2 ; Evaluate with extra precision.
- X (cond ((complexp x)
- X (mysin-complex x))
- X ((< x 0)
- X (- (mysin-raw (- x))) ; Always call mysin-raw with x >= 0.
- X (t (mysin-raw x))))))
- X
- X(defmath mysin-raw (x)
- X (cond ((>= x 7)
- X (mysin-raw (% x (two-pi)))) ; Now x < 7.
- X ((> x (pi-over-2))
- X (- (mysin-raw (- x (pi))))) ; Now -pi/2 <= x <= pi/2.
- X ((> x (pi-over-4))
- X (mycos-raw (- x (pi-over-2)))) ; Now -pi/2 <= x <= pi/4.
- X ((< x (- (pi-over-4)))
- X (- (mycos-raw (+ x (pi-over-2))))) ; Now -pi/4 <= x <= pi/4,
- X (t (mysin-series x)))) ; so the series will be efficient.
- X@end example
- X
- X@noindent
- Xwhere @code{mysin-complex} is an appropriate function to handle complex
- Xnumbers, @code{mysin-series} is the routine to compute the sine Taylor
- Xseries as before, and @code{mycos-raw} is a function analogous to
- X@code{mysin-raw} for cosines.
- X
- XThe strategy is to ensure that @samp{x} is nonnegative before calling
- X@code{mysin-raw}. This function then recursively reduces its argument
- Xto a suitable range, namely, plus-or-minus @samp{pi/4}. Note that each
- Xtest, and particularly the first comparison against 7, is designed so
- Xthat small roundoff errors cannnot produce an infinite loop. (Suppose
- Xwe compared with @samp{(two-pi)} instead; if due to roundoff problems
- Xthe modulo operator ever returned @samp{(two-pi)} exactly, an infinite
- Xrecursion could result!) We use modulo only for arguments that will
- Xclearly get reduced, knowing that the next rule will catch any reductions
- Xthat this rule misses.
- X
- XIf a program is being written for general use, it is important to code
- Xit carefully as shown in this second example. For quick-and-dirty programs,
- Xwhen you know that your own use of the sine function will never encounter
- Xa large argument, a simpler program like the first one shown is fine.
- X
- X@node Internals, , Example Definitions, Lisp Definitions
- X@subsection Calculator Internals
- X
- XThis chapter describes the Lisp functions defined by the Calculator that
- Xmay be of use to user-written Calculator programs (as described in the
- Xrest of this chapter). These functions are shown by their names as they
- Xconventionally appear in @code{defmath}. Their full Lisp names are
- Xgenerally gotten by prepending @samp{calcFunc-} or @samp{math-} to their
- Xapparent names. (Names that begin with @samp{calc-} are already in
- Xtheir full Lisp form.) You can use the actual full names instead if you
- Xprefer them, or if you are calling these functions from regular Lisp.
- X
- XLittle distinction is made here between functions in the main Calc
- Xbody and functions in the extensions module. Because @code{defmath}
- Xitself is in the extensions, user-written code generally always
- Xexecutes with the extensions already loaded, so this is not an issue.
- XIf you are doing something special, check carefully to make sure each
- Xfunction you are using is from the main body; be sure to call
- X@samp{(calc-extensions)} before using any function from the extensions
- Xpackage if you can't prove the extensions will already have been loaded.
- X
- X@menu
- X* Data Type Formats::
- X* Interactive Lisp Functions::
- X* Stack Lisp Functions::
- X* Predicates::
- X* Computational Lisp Functions::
- X* Vector Lisp Functions::
- X* Symbolic Lisp Functions::
- X* Formatting Lisp Functions::
- X* Lisp Variables::
- X* Hooks::
- X@end menu
- X
- X@node Data Type Formats, Interactive Lisp Functions, Internals, Internals
- X@subsubsection Data Type Formats
- X
- XIntegers are stored in either of two ways, depending on their magnitude.
- XIntegers less than one million in absolute value are stored as standard
- XLisp integers. This is the only storage format for Calc data objects
- Xwhich is not a Lisp list.
- X
- XLarge integers are stored as a list of the form @samp{(bigpos @var{d0}
- X@var{d1} @var{d2} @dots{}} for positive integers 1000000 or more, or
- X@samp{(bigneg @var{d0} @var{d1} @var{d2} @dots{}} for negative integers
- X-1000000 or less. Each @var{d} is a base-1000 ``digit,'' a Lisp integer
- Xfrom 0 to 999. The least significant digit is @var{d0}; the last digit,
- X@var{dn}, which is always nonzero, is the most significant digit. For
- Xexample, the integer -12345678 is stored as @samp{(bigneg 678 345 12)}.
- X
- XThe distinction between small and large integers is entirely hidden from
- Xthe user. In @code{defmath} definitions, the Lisp predicate @code{integerp}
- Xreturns true for either kind of integer, and in general both big and small
- Xintegers are accepted anywhere the word ``integer'' is used in this manual.
- XIf the distinction must be made, native Lisp integers are called @dfn{fixnums}
- Xand large integers are called @dfn{bignums}.
- X
- XFractions are stored as a list of the form, @samp{(frac @var{n} @var{d})}
- Xwhere @var{n} is an integer (big or small) numerator, @var{d} is an
- Xinteger denominator greater than one, and @var{n} and @var{d} are relatively
- Xprime. Note that fractions where @var{d} is one are automatically converted
- Xto plain integers by all math routines; fractions where @var{d} is negative
- Xare normalized by negating the numerator and denominator.
- X
- XFloating-point numbers are stored in the form, @samp{(float @var{mant}
- X@var{exp})}, where @var{mant} (the ``mantissa'') is an integer less than
- X@samp{10^@var{p}} in absolute value (@var{p} represents the current
- Xprecision), and @var{exp} (the ``exponent'') is a fixnum. The value of
- Xthe float is @samp{@var{mant} * 10^@var{exp}}. For example, the number
- X-3.14 is stored as @samp{(float -314 -2) = -314*10^-2}. Other constraints
- Xare that the number 0.0 is always stored as @samp{(float 0 0)}, and,
- Xexcept for the 0.0 case, the rightmost base-10 digit of @var{mant} is
- Xalways nonzero. (If the rightmost digit is zero, the number is
- Xrearranged by dividing @var{mant} by ten and incrementing @var{exp}.)@refill
- X
- XRectangular complex numbers are stored in the form @samp{(cplx @var{re}
- X@var{im})}, where @var{re} and @var{im} are each real numbers, either
- Xintegers, fractions, or floats. The value is @samp{@var{re} + @var{im}i}.
- XThe @var{im} part is nonzero; complex numbers with zero imaginary
- Xcomponents are converted to real numbers automatically.@refill
- X
- XPolar complex numbers are stored in the form @samp{(polar @var{r}
- X@var{theta})}, where @var{r} is a positive real value and @var{theta}
- Xis a real value or HMS form representing an angle. This angle is
- Xusually normalized to lie in the interval @samp{(-180 .. 180)} degrees,
- Xor @samp{(-pi .. pi)} radians, according to the current angular mode.
- XIf the angle is 0 the value is converted to a real number automatically.
- X(If the angle is 180 degrees, the value is usually also converted to a
- Xnegative real number.)@refill
- X
- XHours-minutes-seconds forms are stored as @samp{(hms @var{h} @var{m}
- X@var{s})}, where @var{h} is an integer or an integer-valued float (i.e.,
- Xa float with @samp{@var{exp} >= 0}), @var{m} is an integer or integer-valued
- Xfloat in the range @samp{[0 .. 60)}, and @var{s} is any real number in the
- Xrange @samp{[0 .. 60)}.@refill
- X
- XModulo forms are stored as @samp{(mod @var{n} @var{m})}, where @var{m} is a
- Xpositive real number or HMS form, and @var{n} is a real number or HMS
- Xform in the range @samp{[0 .. @var{m})}.
- X
- XError forms are stored as @samp{(sdev @var{x} @var{sigma})}, where @var{x}
- Xis the mean value and @var{sigma} is the standard deviation. Each
- Xcomponent is either a real number, an HMS form, or a symbolic object
- X(a variable or function call). If @var{sigma} is zero, the value is
- Xconverted to a plain real number. If @var{sigma} is negative, it is
- Xautomatically normalized to be positive.
- X
- XInterval forms are stored as @samp{(intv @var{mask} @var{lo} @var{hi})},
- Xwhere @var{mask} is one of the integers 0, 1, 2, or 3, and @var{lo} and
- X@var{hi} are real numbers, HMS forms, or symbolic objects. The @var{mask}
- Xis a binary integer where 1 represents the fact that the interval is
- Xclosed on the high end, and 2 represents the fact that it is closed on
- Xthe low end. (Thus 3 represents a fully closed interval.) The interval
- X@samp{(intv 3 @var{x} @var{x})} is converted to the plain number @var{x};
- Xintervals @samp{(intv @var{mask} @var{x} @var{x})} for any other @var{mask}
- Xrepresent empty intervals. If @var{hi} is less than @var{lo}, the interval
- Xis converted to a standard empty interval by replacing @var{hi} with @var{lo}.
- X
- XVectors are stored as @samp{(vec @var{v1} @var{v2} @dots{})}, where @var{v1}
- Xis the first element of the vector, @var{v2} is the second, and so on.
- XAn empty vector is stored as @samp{(vec)}. A matrix is simply a vector
- Xwhere all @var{v}'s are themselves vectors of equal lengths.
- X
- XVariables are stored as @samp{(var @var{name} @var{sym})}, where
- X@var{name} is a Lisp symbol whose print name is used as the visible name
- Xof the variable, and @var{sym} is a Lisp symbol in which the variable's
- Xvalue is actually stored. Thus, @samp{(var pi var-pi)} represents the
- Xspecial constant @samp{pi}. Almost always, the form is @samp{(var
- X@var{v} var-@var{v})}. If the variable name was entered with
- Xunderscores (which are converted to hyphens internally), the form is
- X@samp{(var @var{v} @var{v})}. The value of a variable is the Calc
- Xobject stored in its @var{sym} symbol's value cell. If the symbol's
- Xvalue cell is void or if it contains @code{nil}, the variable has no
- Xvalue. Special constants have the form @samp{(special-const
- X@var{value})} stored in their value cell, where @var{value} is a formula
- Xwhich is evaluated when the constant's value is requested. Variables
- Xwhich represent units are not stored in any special way; they are units
- Xonly because their names appear in the units table.@refill
- X
- XA Lisp list with any other symbol as the first element is a function call.
- XThe symbols @code{+}, @code{-}, @code{*}, @code{/}, @code{%}, @code{^},
- Xand @code{|} represent special binary operators; these lists are always
- Xof the form @samp{(@var{op} @var{lhs} @var{rhs})} where @var{lhs} is the
- Xsub-formula on the lefthand side and @var{rhs} is the sub-formula on the
- Xright. The symbol @code{neg} represents unary negation; this list is always
- Xof the form @samp{(neg @var{arg})}. Any other symbol @var{func} represents a
- Xfunction that would be displayed in function-call notation; the symbol
- X@var{func} is in general always of the form @samp{calcFunc-@var{name}}.
- XThe function cell of the symbol @var{func} should contain a Lisp function
- Xfor evaluating a call to @var{func}. This function is passed the remaining
- Xelements of the list (themselves already evaluated) as arguments; such
- Xfunctions should return @code{nil} or call @code{reject-arg} to signify
- Xthat they should be left in symbolic form, or they should return a Calc
- Xobject which represents their value, or a list of such objects if they
- Xwish to return multiple values. (The latter case is allowed only for
- Xfunctions which are the outer-level call in an expression whose value is
- Xabout to be pushed on the stack.)@refill
- X
- X@node Interactive Lisp Functions, Stack Lisp Functions, Data Type Formats, Internals
- X@subsubsection Interactive Functions
- X
- XThe functions described here are used in implementing interactive Calc
- Xcommands.
- X
- X@defun calc-set-command-flag flag
- XSet the command flag @var{flag}. This is generally a Lisp symbol, but
- Xmay in fact by anything. The effect is to add @var{flag} to the list
- Xstored in the variable @code{calc-command-flags}, unless it is already
- Xthere. @xref{Defining Simple Commands}.
- X@end defun
- X
- X@defun calc-clear-command-flag flag
- XIf @var{flag} appears among the list of currently-set command flags,
- Xremove it from that list.
- X@end defun
- X
- X@defun calc-record-undo rec
- XAdd the ``undo record'' @var{rec} to the list of steps to take if the
- Xcurrent operation should need to be undone. Stack push and pop functions
- Xautomatically call @code{calc-record-undo}, so the kinds of undo records
- Xyou might need to create take the form @samp{(set @var{sym} @var{value})},
- Xwhich says that the Lisp variable @var{sym} was changed and had previously
- Xcontained @var{value}; @samp{(store @var{var} @var{value})} which says that
- Xthe Calc variable @var{var} (a string which is the name of the symbol that
- Xcontains the variable's value) was stored and its previous value was
- X@var{value} (either a Calc data object, or @var{nil} if the variable was
- Xpreviously void); or @samp{(eval @var{undo} @var{redo} @var{args} @dots{})},
- Xwhich means that to undo requires calling the function @samp{(@var{undo}
- X@var{args} @dots{})} and, if the undo is later redone, calling
- X@samp{(@var{redo} @var{args} @dots{})}.@refill
- X@end defun
- X
- X@defun calc-record-why msg args
- XRecord the error or warning message @var{msg}, which is normally a string.
- XThis message will be replayed if the user types @kbd{w} (@code{calc-why});
- Xthe first such message recorded for a command will be replayed automatically
- Xif the user has turned on @code{calc-auto-why} mode. If one or more
- X@var{args} are present, the displayed message will be of the form,
- X@samp{@var{msg}: @var{arg1}, @var{arg2}, @dots{}}, where the arguments are
- Xformatted on the assumption that they are either strings or Calc objects of
- Xsome sort. If @var{msg} is a symbol, it is the name of a Calc predicate
- X(such as @code{integerp} or @code{numvecp}) which the arguments did not
- Xsatisfy; it is expanded to a suitable string such as ``Expected an
- Xinteger.'' The @code{reject-arg} function calls @code{calc-record-why}
- Xautomatically; @pxref{Predicates}.@refill
- X@end defun
- X
- X@defun calc-is-inverse
- XThis predicate returns true if the current command is inverse,
- Xi.e., if the Inverse (@kbd{I} key) flag was set.
- X@end defun
- X
- X@defun calc-is-hyperbolic
- XThis predicate is the analogous function for the @kbd{H} key.
- X@end defun
- X
- X@node Stack Lisp Functions, Predicates, Interactive Lisp Functions, Internals
- X@subsubsection Stack-Oriented Functions
- X
- XThe functions described here perform various operations on the Calc
- Xstack and trail. They are to be used in interactive Calc commands.
- X
- X@defun calc-push-list vals n
- XPush the Calc objects in list @var{vals} onto the stack at stack level
- X@var{n}. If @var{n} is omitted it defaults to 1, so that the elements
- Xare pushed at the top of the stack. If @var{n} is greater than 1, the
- Xelements will be inserted into the stack so that the last element will
- Xend up at level @var{n}, the next-to-last at level @var{n}+1, etc.
- XThe elements of @var{vals} are assumed to be valid Calc objects, and
- Xare not evaluated or renormalized in any way. If @var{vals} is an
- Xempty list, nothing happens.@refill
- X@end defun
- X
- X@defun calc-top-list n m
- XReturn a list of the @var{n} objects starting at level @var{m} of the
- Xstack. If @var{m} is omitted it defaults to 1, so that the elements are
- Xtaken from the top of the stack. If @var{n} is omitted, it also
- Xdefaults to 1, so that the top stack element (in the form of a
- Xone-element list) is returned. If @var{m} is greater than 1, the
- X@var{m}th stack element will be at the end of the list, the @var{m}+1st
- Xelement will be next-to-last, etc. If @var{n} or @var{m} are out of
- Xrange, the command is aborted with a suitable error message. If @var{n}
- Xis zero, the function returns an empty list. The stack elements are not
- Xevaluated or renormalized.@refill
- X@end defun
- X
- X@defun calc-pop-stack n m
- XRemove the specified elements from the stack. The parameters @var{n}
- Xand @var{m} are defined the same as for @code{calc-top-list}. The return
- Xvalue of @code{calc-pop-stack} is uninteresting.
- X@end defun
- X
- X@defun calc-record-list vals tag
- XThis function records one or more results in the trail. The @var{vals}
- Xare a list of strings or Calc objects. The @var{tag} is the four-character
- Xtag string to identify the values. If @var{tag} is omitted, a blank tag
- Xwill be used.
- X@end defun
- X
- X@defun calc-normalize n
- XThis function takes a Calc object and ``normalizes'' it. At the very
- Xleast this involves re-rounding floating-point values according to the
- Xcurrent precision and other similar jobs. Also, unless the user has
- Xselected no-simplify mode (@pxref{Simplification Modes}), this involves
- Xactually evaluating a formula object by executing the function calls
- Xit contains.
- X@end defun
- X
- X@defun calc-top-list-n n m
- XThis function is identical to @code{calc-top-list}, except that it calls
- X@code{calc-normalize} on the values that it takes from the stack. They
- Xare also passed through @code{check-complete}, so that incomplete
- Xobjects will be rejected with an error message. All computational
- Xcommands should use this in preference to @code{calc-top-list}; the only
- Xstandard Calc commands that operate on the stack without normalizing
- Xare stack management commands like @code{calc-enter} and @code{calc-roll-up}.
- X@end defun
- X
- X@defun calc-top-n m
- XThis function is a convenient form of @code{calc-top-list-n} in which only
- Xa single element of the stack is taken and returned, rather than a list
- Xof elements.
- X@end defun
- X
- X@defun calc-enter-result n tag vals
- XThis function is a convenient interface to most of the above functions.
- XThe @var{vals} argument should be either a single Calc object, or a list
- Xof Calc objects; the object or objects are normalized, and the top @var{n}
- Xstack entries are replaced by the normalized objects. If @var{tag} is
- Xnon-@code{nil}, the normalized objects are also recorded in the trail.
- XA typical stack-based computational command would take the form,
- X
- X@example
- X(calc-enter-result @var{n} @var{tag} (cons 'calcFunc-@var{func}
- X (calc-top-list-n @var{n})))
- X@end example
- X@end defun
- X
- X@defun calc-unary-op tag func arg
- XThis function implements a unary operator that allows a numeric prefix
- Xargument to apply the operator over many stack entries. If the prefix
- Xargument @var{arg} is @code{nil}, this uses @code{calc-enter-result}
- Xas outlined above. Otherwise, it maps the function over several stack
- Xelements; @pxref{Prefix Arguments}. For example,@refill
- X
- X@example
- X(defun calc-zeta (arg)
- X (interactive "P")
- X (calc-unary-op "zeta" 'calcFunc-zeta arg))
- X@end example
- X@end defun
- X
- X@defun calc-binary-op tag func arg ident unary
- XThis function implements a binary operator, analogously to
- X@code{calc-unary-op}. The optional @var{ident} and @var{unary}
- Xarguments specify the behavior when the prefix argument is zero or
- Xone, respectively. If the argument is zero, the value @var{ident}
- Xis pushed onto the stack, if specified, otherwise an error message
- Xis displayed. If the argument is one, the unary function @var{unary}
- Xis applied to the top stack element, or, if @var{unary} is not
- Xspecified, nothing happens. When the argument is two or more,
- Xthe binary function @var{func} is reduced across the top @var{arg}
- Xstack elements; when the argument is negative, the function is
- Xmapped between the next-to-top -@var{arg} stack elements and the
- Xtop element.@refill
- X@end defun
- X
- X@defun calc-stack-size
- XReturn the number of elements on the stack as an integer. This count
- Xdoes not include elements that have been temporarily hidden by stack
- Xtruncation; @pxref{Truncating the Stack}.
- X@end defun
- X
- X@defun calc-cursor-stack-index n
- XMove the point to the @var{n}th stack entry. If @var{n} is zero, this
- Xwill be the @samp{.} line. If @var{n} is from 1 to the current stack size,
- Xthis will be the beginning of the first line of that stack entry's display.
- XIf line numbers are enabled, this will move to the first character of the
- Xline number, not the stack entry itself.@refill
- X@end defun
- X
- X@defun calc-substack-height n
- XReturn the number of lines between the beginning of the @var{n}th stack
- Xentry and the bottom of the buffer. If @var{n} is zero, this
- Xwill be one (assuming no stack truncation). If all stack entries are
- Xone line long (i.e., no matrices are displayed), the return value will
- Xbe equal @var{n}+1 as long as @var{n} is in range.@refill
- X@end defun
- X
- X@defun calc-refresh
- XErase the @code{*Calculator*} buffer and reformat its contents from memory.
- XThis must be called after changing any parameter, such as the current
- Xdisplay radix, which might change the appearance of existing stack
- Xentries. (During a keyboard macro invoked by the @kbd{K} key, refreshing
- Xis suppressed, but a flag is set so that the entire stack will be refreshed
- Xrather than just the top few elements when the macro finishes.)@refill
- X@end defun
- X
- X@node Predicates, Computational Lisp Functions, Stack Lisp Functions, Internals
- X@subsubsection Predicates
- X
- XThe functions described here are predicates, that is, they return a
- Xtrue/false value where @code{nil} means false and anything else means
- Xtrue. These predicates are expanded by @code{defmath}, for example,
- Xfrom @code{zerop} to @code{math-zerop}. In many cases they correspond
- Xto native Lisp functions by the same name, but are extended to cover
- Xthe full range of Calc data types.
- X
- X@defun zerop x
- XReturns true if @var{x} is numerically zero, in any of the Calc data
- Xtypes. (Note that for some types, such as error forms and intervals,
- Xit never makes sense to return true.) In @code{defmath}, the expression
- X@samp{(= x 0)} will automatically be converted to @samp{(math-zerop x)},
- Xand @samp{(/= x 0)} will be converted to @samp{(not (math-zerop x))}.
- X@end defun
- X
- X@defun negp x
- XReturns true if @var{x} is negative. This accepts negative real numbers
- Xof various types, negative HMS forms, and intervals in which all
- Xincluded values are negative. In @code{defmath}, the expression
- X@samp{(< x 0)} will automatically be converted to @samp{(math-negp x)},
- Xand @samp{(>= x 0)} will be converted to samp{(not (math-negp x))}.
- X@end defun
- X
- X@defun posp x
- XReturns true if @var{x} is positive (and non-zero).
- X@end defun
- X
- X@defun looks-negp x
- XReturns true if @var{x} is ``negative-looking.'' This returns true if
- X@var{x} is a negative number, or a formula with a leading minus sign
- Xsuch as @samp{-a/b}. In other words, this is an object which can be
- Xmade simpler by calling @code{(- @var{x})}.
- X@end defun
- X
- X@defun integerp x
- XReturns true if @var{x} is an integer of any size.
- X@end defun
- X
- X@defun fixnump x
- XReturns true if @var{x} is a native Lisp integer.
- X@end defun
- X
- X@defun natnump x
- XReturns true if @var{x} is a nonnegative integer of any size.
- X@end defun
- X
- X@defun fixnatnump x
- XReturns true if @var{x} is a nonnegative Lisp integer.
- X@end defun
- X
- X@defun num-integerp x
- XReturns true if @var{x} is numerically an integer, i.e., either a
- Xtrue integer or a float with no significant digits to the right of
- Xthe decimal point.
- X@end defun
- X
- X@defun messy-integerp x
- XReturns true if @var{x} is numerically, but not literally, an integer.
- XA value is @code{num-integerp} if it is @code{integerp} or
- X@code{messy-integerp} (but it is never both at once).
- X@end defun
- X
- X@defun num-natnump x
- XReturns true if @var{x} is numerically a nonnegative integer.
- X@end defun
- X
- X@defun evenp x
- XReturns true if @var{x} is an even integer.
- X@end defun
- X
- X@defun looks-evenp x
- XReturns true if @var{x} is an even integer, or a formula with a leading
- Xmultiplicative coefficient which is an even integer.
- X@end defun
- X
- X@defun oddp x
- XReturns true if @var{x} is an odd integer.
- X@end defun
- X
- X@defun provably-integerp x
- XReturns true if @var{x} is an integer, or a formula whose result
- Xis guaranteed to be an integer (such as a call to @code{floor}).
- X@end defun
- X
- X@defun ratp x
- XReturns true if @var{x} is a rational number, i.e., an integer or a
- Xfraction.
- X@end defun
- X
- X@defun realp x
- XReturns true if @var{x} is a real number, i.e., an integer, fraction,
- Xor floating-point number.
- X@end defun
- X
- X@defun provably-realp x
- XReturns true if @var{x} is a real number, or a formula whose result
- Xis guaranteed to be real (such as a call to @code{abs}).
- X@end defun
- X
- X@defun anglep x
- XReturns true if @var{x} is a real number or HMS form.
- X@end defun
- X
- X@defun floatp x
- XReturns true if @var{x} is a float, or a complex number, error form,
- Xinterval, or modulo form in which at least one component is a float.
- X@end defun
- X
- X@defun complexp x
- XReturns true if @var{x} is a rectangular or polar complex number
- X(but not a real number).
- X@end defun
- X
- X@defun rect-complexp x
- XReturns true if @var{x} is a rectangular complex number.
- X@end defun
- X
- X@defun polar-complexp x
- XReturns true if @var{x} is a polar complex number.
- X@end defun
- X
- X@defun numberp x
- XReturns true if @var{x} is a real number or a complex number.
- X@end defun
- X
- X@defun scalarp x
- XReturns true if @var{x} is a real or complex number or an HMS form.
- X@end defun
- X
- X@defun vectorp x
- XReturns true if @var{x} is a vector (this simply checks if its argument
- Xis a list whose first element is the symbol @code{vec}).
- X@end defun
- X
- X@defun numvecp x
- XReturns true if @var{x} is a number or vector.
- X@end defun
- X
- X@defun matrixp x
- XReturns true if @var{x} is a matrix, i.e., a vector of one or more vectors,
- Xall of the same size.
- X@end defun
- X
- X@defun square-matrixp x
- XReturns true if @var{x} is a square matrix.
- X@end defun
- X
- X@defun objectp x
- XReturns true if @var{x} is any numeric Calc object, including real and
- Xcomplex numbers, HMS forms, error forms, intervals, and modulo forms.
- X(Note that error forms and intervals may include formulas as their
- Xcomponents; see @code{constp} below.)
- X@end defun
- X
- X@defun real-objectp x
- XReturns true if @var{x} is any numeric Calc object, in the sense of
- X@code{objectp}, except for a complex number.
- X@end defun
- X
- X@defun objvecp x
- XReturns true if @var{x} is an object or a vector. This also accepts
- Xincomplete objects, but it rejects variables and formulas (except as
- Xmentioned above for @code{objectp}).
- X@end defun
- X
- X@defun primp x
- XReturns true if @var{x} is a ``primitive'' or ``atomic'' Calc object,
- Xi.e., one whose components cannot be regarded as sub-formulas. This
- Xincludes variables, and all @code{objectp} types except error forms
- Xand intervals.
- X@end defun
- X
- X@defun constp x
- XReturns true if @var{x} is constant, i.e., a real or complex number,
- XHMS form, or error form, interval, or vector all of whose components
- Xare @code{constp}.
- X@end defun
- X
- X@defun lessp x y
- XReturns true if @var{x} is numerically less than @var{y}. Returns false
- Xif @var{x} is greater than or equal to @var{y}, or if the order is
- Xundefined or cannot be determined. Generally speaking, this works
- Xby checking whether @samp{@var{x} - @var{y}} is @code{negp}. In
- X@code{defmath}, the expression @samp{(< x y)} will automatically be
- Xconverted to @samp{(lessp x y)}; expressions involving @code{>}, @code{<=},
- Xand @code{>=} are similarly converted in terms of @code{lessp}.@refill
- X@end defun
- X
- X@defun beforep x y
- XReturns true if @var{x} comes before @var{y} in a canonical ordering
- Xof Calc objects. If @var{x} and @var{y} are both real numbers, this
- Xwill be the same as @code{lessp}. But whereas @code{lessp} considers
- Xother types of objects to be unordered, @code{beforep} puts any two
- Xobjects into a definite, consistent order. One application of
- X@code{beforep} is that algebraic simplification rearranges the terms
- Xin a product into canonical order, so that @samp{x y + y x} can
- Xcheaply be simplified to @samp{2 x y}.
- X@end defun
- X
- X@defun equal x y
- XThis is the standard Lisp @code{equal} predicate; it returns true if
- X@var{x} and @var{y} are structurally identical. This is the usual way
- Xto compare numbers for equality, but note that @code{equal} will treat
- X0 and 0.0 as different.
- X@end defun
- X
- X@defun math-equal x y
- XReturns true if @var{x} and @var{y} are numerically equal, either because
- Xthey are @code{equal}, or because their difference is @code{zerop}. In
- X@code{defmath}, the expression @samp{(= x y)} will automatically be
- Xconverted to @samp{(math-equal x y)}.
- X@end defun
- X
- X@defun equal-int x n
- XReturns true if @var{x} and @var{n} are numerically equal, where @var{n}
- Xis a fixnum which is not a multiple of 10. This will automatically be
- Xused by @code{defmath} in place of the more general @code{math-equal}
- Xwhenever possible.@refill
- X@end defun
- X
- X@defun nearly-equal x y
- XReturns true if @var{x} and @var{y}, as floating-point numbers, are
- Xequal except possibly in the last decimal place. For example,
- X314.159 and 314.166 are considered nearly equal if the current
- Xprecision is 6 (since they differ by 7 units), but not if the current
- Xprecision is 7 (since they differ by 70 units). Most functions which
- Xuse series expansions use @code{with-extra-prec} to evaluate the
- Xseries with 2 extra digits of precision, then use @code{nearly-equal}
- Xto decide when the series has converged; this guards against cumulative
- Xerror in the series evaluation without doing extra work which would be
- Xlost when the result is rounded back down to the current precision.
- XIn @code{defmath}, this can be written @samp{(~= @var{x} @var{y})}.
- X@end defun
- X
- X@defun nearly-zerop x y
- XReturns true if @var{x} is nearly zero, compared to @var{y}. This
- Xchecks whether @var{x} plus @var{y} would by be @code{nearly-equal}
- Xto @var{y} itself, to within the current precision, in other words,
- Xif adding @var{x} to @var{y} would have a negligible effect on @var{y}
- SHAR_EOF
- echo "End of part 18"
- echo "File calc.texinfo is continued in part 19"
- echo "19" > s2_seq_.tmp
- exit 0
-